#include "perlin.hh"
// stb_perlin.h - v0.2 - perlin noise
// public domain single-file C implementation by Sean Barrett
//
// modified to be used in c++ by eXerigumo Clanjor.

// not same permutation table as Perlin's reference to avoid copyright issues;
// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/
// @OPTIMIZE: should this be unsigned char instead of int for cache?
static int stb__perlin_randtab[512] =
{
	 23, 125, 161,  52, 103, 117,  70,  37, 247, 101, 203, 169, 124, 126,  44, 123,
	152, 238, 145,  45, 171, 114, 253,  10, 192, 136,   4, 157, 249,  30,  35,  72,
	175,  63,  77,  90, 181,  16,  96, 111, 133, 104,  75, 162,  93,  56,  66, 240,
	  8,  50,  84, 229,  49, 210, 173, 239, 141,   1,  87,  18,   2, 198, 143,  57,
	225, 160,  58, 217, 168, 206, 245, 204, 199,   6,  73,  60,  20, 230, 211, 233,
	 94, 200,  88,   9,  74, 155,  33,  15, 219, 130, 226, 202,  83, 236,  42, 172,
	165, 218,  55, 222,  46, 107,  98, 154, 109,  67, 196, 178, 127, 158,  13, 243,
	 65,  79, 166, 248,  25, 224, 115,  80,  68,  51, 184, 128, 232, 208, 151, 122,
	 26, 212, 105,  43, 179, 213, 235, 148, 146,  89,  14, 195,  28,  78, 112,  76,
	250,  47,  24, 251, 140, 108, 186, 190, 228, 170, 183, 139,  39, 188, 244, 246,
	132,  48, 119, 144, 180, 138, 134, 193,  82, 182, 120, 121,  86, 220, 209,   3,
	 91, 241, 149,  85, 205, 150, 113, 216,  31, 100,  41, 164, 177, 214, 153, 231,
	 38,  71, 185, 174,  97, 201,  29,  95,   7,  92,  54, 254, 191, 118,  34, 221,
	131,  11, 163,  99, 234,  81, 227, 147, 156, 176,  17, 142,  69,  12, 110,  62,
	 27, 255,   0, 194,  59, 116, 242, 252,  19,  21, 187,  53, 207, 129,  64, 135,
	 61,  40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137,  36,  32,  22,   5,

	// and a second copy so we don't need an extra mask or static initializer
	 23, 125, 161,  52, 103, 117,  70,  37, 247, 101, 203, 169, 124, 126,  44, 123,
	152, 238, 145,  45, 171, 114, 253,  10, 192, 136,   4, 157, 249,  30,  35,  72,
	175,  63,  77,  90, 181,  16,  96, 111, 133, 104,  75, 162,  93,  56,  66, 240,
	  8,  50,  84, 229,  49, 210, 173, 239, 141,   1,  87,  18,   2, 198, 143,  57,
	225, 160,  58, 217, 168, 206, 245, 204, 199,   6,  73,  60,  20, 230, 211, 233,
	 94, 200,  88,   9,  74, 155,  33,  15, 219, 130, 226, 202,  83, 236,  42, 172,
	165, 218,  55, 222,  46, 107,  98, 154, 109,  67, 196, 178, 127, 158,  13, 243,
	 65,  79, 166, 248,  25, 224, 115,  80,  68,  51, 184, 128, 232, 208, 151, 122,
	 26, 212, 105,  43, 179, 213, 235, 148, 146,  89,  14, 195,  28,  78, 112,  76,
	250,  47,  24, 251, 140, 108, 186, 190, 228, 170, 183, 139,  39, 188, 244, 246,
	132,  48, 119, 144, 180, 138, 134, 193,  82, 182, 120, 121,  86, 220, 209,   3,
	 91, 241, 149,  85, 205, 150, 113, 216,  31, 100,  41, 164, 177, 214, 153, 231,
	 38,  71, 185, 174,  97, 201,  29,  95,   7,  92,  54, 254, 191, 118,  34, 221,
	131,  11, 163,  99, 234,  81, 227, 147, 156, 176,  17, 142,  69,  12, 110,  62,
	 27, 255,   0, 194,  59, 116, 242, 252,  19,  21, 187,  53, 207, 129,  64, 135,
	 61,  40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137,  36,  32,  22,   5,
};

static float lerp(float a, float b, float t)
{
	return a + (b-a) * t;
}

// different grad function from Perlin's,
// but easy to modify to match reference
static float grad(int hash, float x, float y, float z)
{
	static float basis[12][4] =
	{
		{  1, 1, 0 },
		{ -1, 1, 0 },
		{  1,-1, 0 },
		{ -1,-1, 0 },
		{  1, 0, 1 },
		{ -1, 0, 1 },
		{  1, 0,-1 },
		{ -1, 0,-1 },
		{  0, 1, 1 },
		{  0,-1, 1 },
		{  0, 1,-1 },
		{  0,-1,-1 },
	};

	// perlin's gradient has 12 cases so some get used 1/16th of the time
	// and some 2/16ths. We reduce bias by changing those fractions
	// to 5/16ths and 6/16ths, and the same 4 cases get the extra weight.
	static unsigned char indices[64] =
	{
		0,1,2,3,4,5,6,7,8,9,10,11,
		0,9,1,11,
		0,1,2,3,4,5,6,7,8,9,10,11,
		0,1,2,3,4,5,6,7,8,9,10,11,
		0,1,2,3,4,5,6,7,8,9,10,11,
		0,1,2,3,4,5,6,7,8,9,10,11,
	};

	// if you use reference permutation table,
	// change 63 below to 15 to match reference
	float *grad = basis[indices[hash & 63]];
	return grad[0]*x + grad[1]*y + grad[2]*z;
}

namespace stb
{
	float perlin(float x, float y, float z,
			int x_wrap, int y_wrap, int z_wrap)
	{
		float u,v,w;
		float n000,n001,n010,n011,n100,n101,n110,n111;
		float n00,n01,n10,n11;
		float n0,n1;

		unsigned int x_mask = (x_wrap-1) & 255;
		unsigned int y_mask = (y_wrap-1) & 255;
		unsigned int z_mask = (z_wrap-1) & 255;
		int px = (int) /*floor*/(x);
		int py = (int) /*floor*/(y);
		int pz = (int) /*floor*/(z);
		int x0 = px & x_mask, x1 = (px+1) & x_mask;
		int y0 = py & y_mask, y1 = (py+1) & y_mask;
		int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
		int r0,r1, r00,r01,r10,r11;

#define ease(a)   (((a*6-15)*a + 10) * a * a * a)
		x -= px; u = ease(x);
		y -= py; v = ease(y);
		z -= pz; w = ease(z);
#undef ease

		r0 = stb__perlin_randtab[x0];
		r1 = stb__perlin_randtab[x1];

		r00 = stb__perlin_randtab[r0+y0];
		r01 = stb__perlin_randtab[r0+y1];
		r10 = stb__perlin_randtab[r1+y0];
		r11 = stb__perlin_randtab[r1+y1];

		n000 = grad(stb__perlin_randtab[r00+z0], x  , y  , z   );
		n001 = grad(stb__perlin_randtab[r00+z1], x  , y  , z-1 );
		n010 = grad(stb__perlin_randtab[r01+z0], x  , y-1, z   );
		n011 = grad(stb__perlin_randtab[r01+z1], x  , y-1, z-1 );
		n100 = grad(stb__perlin_randtab[r10+z0], x-1, y  , z   );
		n101 = grad(stb__perlin_randtab[r10+z1], x-1, y  , z-1 );
		n110 = grad(stb__perlin_randtab[r11+z0], x-1, y-1, z   );
		n111 = grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 );

		n00 = lerp(n000,n001,w);
		n01 = lerp(n010,n011,w);
		n10 = lerp(n100,n101,w);
		n11 = lerp(n110,n111,w);

		n0 = lerp(n00,n01,v);
		n1 = lerp(n10,n11,v);

		return lerp(n0,n1,u);
	}
}

